package org.asiainfo.common.mybatis.stream.config;

import cn.hutool.core.convert.Convert;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.datasource.DataSourceDecipher;
import com.mybatisflex.core.datasource.DataSourceManager;
import com.mybatisflex.core.keygen.KeyGenerators;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.logicdelete.impl.IntegerLogicDeleteProcessor;
import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.asiainfo.common.core.utils.SpringUtils;
import org.asiainfo.common.mybatis.stream.core.domain.BaseEntity;
import org.asiainfo.common.mybatis.stream.decipher.Decipher;
import org.asiainfo.common.mybatis.stream.factory.MybatisFlexMessageFactory;
import org.asiainfo.common.mybatis.stream.listener.EntityInsertListener;
import org.asiainfo.common.mybatis.stream.listener.EntityUpdateListener;
import org.asiainfo.common.mybatis.stream.reporter.MybatisFlexMessageReporter;
import org.asiainfo.common.mybatis.stream.strategy.FlexDataSourceStrategy;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * mybatis-flex 配置
 *
 * @author dotor-ww
 */
@AutoConfiguration
@EnableTransactionManagement(proxyTargetClass = true)
@RequiredArgsConstructor
@Slf4j
public class MyBatisFlexConfiguration implements MyBatisFlexCustomizer {

    private final MybatisFlexMessageFactory mybatisFlexMessageFactory;

    private final MybatisFlexMessageReporter mybatisFlexMessageReporter;

    /**
     * 数据源解密
     *
     * @return 数据源
     */
    @Bean
    public DataSourceDecipher dataSourceDecipher() {
        return new Decipher();
    }

    /**
     * 自定义配置
     *
     * @param globalConfig 全局配置
     */
    @SneakyThrows
    @Override
    public void customize(FlexGlobalConfig globalConfig) {
        //全局主键生成ID策略
        FlexGlobalConfig.KeyConfig keyConfig = new FlexGlobalConfig.KeyConfig();
        keyConfig.setKeyType(KeyType.Generator);
        keyConfig.setValue(KeyGenerators.flexId);
        keyConfig.setBefore(true);
        FlexGlobalConfig.getDefaultConfig().setKeyConfig(keyConfig);
        //注册全局数据填充监听器
        globalConfig.registerInsertListener(new EntityInsertListener(), BaseEntity.class);
        globalConfig.registerUpdateListener(new EntityUpdateListener(), BaseEntity.class);
        //全局配置逻辑删除字段
        FlexGlobalConfig.getDefaultConfig().setLogicDeleteColumn("del_flag");
        //是否开启租户模式
        if (Convert.toBool(SpringUtils.getProperty("tenant.enabled"), false)) {
            //全局配置租户字段
            FlexGlobalConfig.getDefaultConfig().setTenantColumn("tenant_id");
        }
        //设置数据库正常时的值
        globalConfig.setNormalValueOfLogicDelete("0");
        //设置数据已被删除时的值
        globalConfig.setDeletedValueOfLogicDelete("1");
        //配置逻辑删除处理器
        LogicDeleteManager.setProcessor(new IntegerLogicDeleteProcessor());
        //开启审计功能
        AuditManager.setAuditEnable(true);
        //设置 SQL 审计消息工厂
        AuditManager.setMessageFactory(mybatisFlexMessageFactory);
        //设置 SQL 审计收集器
        AuditManager.setMessageReporter(mybatisFlexMessageReporter);
        //数据源分片 读写分离策略
        DataSourceManager.setDataSourceShardingStrategy(new FlexDataSourceStrategy());
    }
}
